package com.yangchao.webflux.controler;

import com.yangchao.webflux.vo.UserVO;
import org.slf4j.Logger;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.File;
import java.time.Duration;


@RestController
@RequestMapping("")
public class MyRestController {

    Logger log = org.slf4j.LoggerFactory.getLogger(MyRestController.class);


    @GetMapping("/users/{userId}")
    public Mono<UserVO> getUser(@PathVariable Long userId) {
        log.info("userId = {}" , userId);
        return Mono.just(new UserVO(){{
            setId(1L);
            setName("user01");
        }});
    }

    @GetMapping("/users")
    public Flux<UserVO> getUser() {
        log.info("users");
        return Flux.just(new UserVO(){{
            setId(1L);
            setName("user01");
        }},new UserVO(){{
            setId(2L);
            setName("user02");
        }});
    }

    @PostMapping(value = "/users",produces= MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<UserVO> getUser2(@RequestBody UserVO userVO) {
        log.info("userVO = {}", userVO);
        return Flux.interval(Duration.ofSeconds(1)).map(i -> {
            return new UserVO() {{
                setId(i);
                setName("user" + userVO.getName() + ":" + i);
            }};
        });
    }

    //sse
    // @GetMapping(value = "/sse",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    // public Flux<UserVO> getUser2() {
    //     Flux<UserVO> userVOFlux = Flux.range(1, 100).map(i -> {
    //         return new UserVO() {{
    //             setId(Long.valueOf(i));
    //             setName("user" + i);
    //         }};
    //     });
    //     return userVOFlux.delayElements(Duration.ofSeconds(2)).log().limitRate(1,1);
    // }

    @GetMapping(value = "/sse")
    public Flux<ServerSentEvent<UserVO>> getUser3() {
        Flux<UserVO> userVOFlux = Flux.range(1, 100).map(i -> {
            return new UserVO() {{
                setId(Long.valueOf(i));
                setName("user" + i);
            }};
        });
        return userVOFlux.delayElements(Duration.ofSeconds(2)).log().limitRate(1, 1)
                .map(userVO -> {
                    return ServerSentEvent.builder(userVO).build();
                });
    }

    @PostMapping("/upload")
    public Mono<String> handleFileUpload(@RequestPart("file") Mono<FilePart> file) {
        log.info("file = {}" , file);
        return file.flatMap(f -> {
            log.info("filename = {}" , f.filename());
            // 保存文件到本地或进行其他处理
            return f.transferTo(new File("./chapter-03-webflux/src/main/resources/"+f.filename()))
                    .then(Mono.just("File uploaded successfully: " + f.filename()));
        });
    }

    @GetMapping("/err")
    public Flux<UserVO> err() {
        log.info("err");
        throw new RuntimeException("发生了异常");
    }
}